package com.zx._01_基础._011_集合;

import com.zx.common.entity.User;
import com.zx.common.service.UserService;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import org.junit.Test;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StopWatch;

public class ArraylistTest {

    //1.简单操作
    @Test
    public void test01() {
        // 1. 保存数据
        List<String> list = new ArrayList<String>(2);
        list.add("0");
        list.add("1");
        list.add("2");
        System.out.println("1:" + list);// [0, 1, 2]

        // 2. 中间插入数据。数据相互挪移
        list.add(1, "10");
        System.out.println("2:" + list);//[0, 10, 1, 2]

        // 3. foreach变量
        for (String str : list) {
            System.out.println("3:" + str);
        }

        // 4. Iterator变量并删除数据
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            if (Objects.equals(next, "10")) {
                iterator.remove();
            }
        }
        System.out.println("4." + list);//4:[0, 1, 2]

        // 5.查找指定元素的索引值
        int i = Collections.binarySearch(list, "1");
        System.out.println("5:" + i);//5:1

        //6.返回集合中，target子集合第一次出现的位置。没有则返回-1
        int indexOfSubList = Collections.indexOfSubList(list, Arrays.asList("1", "2"));
        System.out.println("6:" + indexOfSubList);//6:1

        //7.返回source集合中，target子集合最后一次出现的位置。没有则返回-1
        int lastIndexOfSubList = Collections.lastIndexOfSubList(list, Arrays.asList("1", "2"));
        System.out.println("7:" + lastIndexOfSubList);//7:1

        // 8.查找自然排序中最大值的元素
        String max = Collections.max(list);
        System.out.println("8:" + max);//8:2

        // 9.将集合中的所有元素替换为object元素
        Collections.fill(list, "666");
        System.out.println("9:" + max);//9:2

        //10.指定元素在集合中出现的次数，
        int frequency = Collections.frequency(list, "666");
        System.out.println("10:" + frequency);//10:3

        //11.将集合中的所有的oldVal值，替换为newVal
        Collections.replaceAll(list, "666", "1");
        System.out.println("11:" + list);// 11:[1, 1, 1]
    }

    // 2.排序 与 反转
    @Test
    public void test02() {
        ArrayList<Integer> list = new ArrayList<>(100);
        list.add(10);
        list.add(1);
        list.add(5);
        list.add(9);
        Collections.sort(list);
        System.out.println(list);// [1, 5, 9, 10]
        Collections.reverse(list);
        System.out.println(list);// [10, 9, 5, 1]

        //4.指定排序规则
        UserService userService = new UserService();
        List<User> all = userService.getAll();
        Collections.sort(all, new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                if (o1.getId() > o2.getId()) {
                    return -1;
                }
                return 1;
            }
        });
    }

    // 3.遍历性能测试
    @Test
    public void test03() {
        /*
			误传：网上都说 ArrayList for遍历的效率高于 LinkedList iterator遍历。这个是错误的
			真实的情况是
				1. for遍历 ，ArrayList 远高于 LinkedList。 根据硬件设备的不同，效率高于百倍以上。原因在于LinkedList的数据结构导致效率低。
				2. foreach， ArrayList 略高于 LinkedList，效率差别不明显
				3. iterator，差别不是很大。 遍历效率是最高的

			int size = 1000;
			int size2 = 1000 * 10;

			017132800  000%  1. array for遍历
			030107800  001%  2. array foreach
			000257100  000%  3. array iterator遍历
			3499635500 097%  1. linked for遍历			明显性能最差
			050740200  001%  2. linked foreach
			000225700  000%  3. linked iterator遍历
		 */
        int size = 1000;
        int size2 = 1000 * 10;
        ArrayList<Integer> li1 = new ArrayList<>(size);
        Random random = new Random();
        for (int i = 0; i < size; i++) {
            li1.add(random.nextInt(100));
        }
        Iterator<Integer> it1 = li1.iterator();

        LinkedList<Integer> li2 = new LinkedList<>();
        for (int i = 0; i < size; i++) {
            li2.add(random.nextInt(100));
        }
        Iterator<Integer> it2 = li2.iterator();

        StopWatch sw = new StopWatch();
        sw.start("1. array for遍历");
        for (int i = 0; i < size2; i++) {
            for (int j = 0; j < li1.size(); j++) {
                li1.get(j);
            }
        }
        sw.stop();

        sw.start("2. array foreach");
        for (int i = 0; i < size2; i++) {
            for (Integer i1 : li1) {
            }
        }
        sw.stop();

        sw.start("3. array iterator遍历");
        for (int i = 0; i < size2; i++) {
            while (it1.hasNext()) {
                it1.next();
            }
        }
        sw.stop();

        sw.start("1. linked for遍历");
        for (int i = 0; i < size2; i++) {
            for (int j = 0; j < li2.size(); j++) {
                li2.get(j);
            }
        }
        sw.stop();

        sw.start("2. linked foreach");
        for (int i = 0; i < size2; i++) {
            for (Integer i2 : li2) {
            }
        }
        sw.stop();

        sw.start("3. linked iterator遍历");
        for (int i = 0; i < size2; i++) {
            while (it2.hasNext()) {
                it2.next();
            }
        }
        sw.stop();

        System.out.println(sw.prettyPrint());
    }

    // 4. 观察扩容过程
    @Test
    public void test04() throws Exception {
        ArrayList<String> li = new ArrayList<>();
        Field findField = ReflectionUtils.findField(ArrayList.class, "elementData");
        findField.setAccessible(true);
        for (int i = 0; i < 100; i++) {
            li.add("1");
            Object[] os = (Object[]) findField.get(li);// 初始化的list是 {}， 且每次扩容的时候，数组以copy的方式重新生成数组
            System.out.println("size = " + li.size() + ", capacity = " + os.length);
        }
        /*
            扩容演示日志：
            size = 1, capacity = 10
            size = 2, capacity = 10
            size = 3, capacity = 10
            size = 4, capacity = 10
            size = 5, capacity = 10
            size = 6, capacity = 10
            size = 7, capacity = 10
            size = 8, capacity = 10
            size = 9, capacity = 10
            size = 10, capacity = 10
            size = 11, capacity = 15   *****在发现数组长度不够的时候，进行扩容
            size = 12, capacity = 15
            size = 13, capacity = 15
            size = 14, capacity = 15
            size = 15, capacity = 15
            size = 16, capacity = 22
            size = 17, capacity = 22
            size = 18, capacity = 22
            size = 19, capacity = 22
            size = 20, capacity = 22
            size = 21, capacity = 22
            size = 22, capacity = 22
            size = 23, capacity = 33 	*****
            size = 24, capacity = 33
            size = 25, capacity = 33
            size = 26, capacity = 33
            size = 27, capacity = 33
            size = 28, capacity = 33
            size = 29, capacity = 33
            size = 30, capacity = 33
            size = 31, capacity = 33
            size = 32, capacity = 33
            size = 33, capacity = 33
            size = 34, capacity = 49	*****
            size = 35, capacity = 49
            size = 36, capacity = 49
            size = 37, capacity = 49
            size = 38, capacity = 49
            size = 39, capacity = 49
            size = 40, capacity = 49
            size = 41, capacity = 49
            size = 42, capacity = 49
            size = 43, capacity = 49
            size = 44, capacity = 49
            size = 45, capacity = 49
            size = 46, capacity = 49
            size = 47, capacity = 49
            size = 48, capacity = 49
            size = 49, capacity = 49
            size = 50, capacity = 73	*****
            size = 51, capacity = 73
            size = 52, capacity = 73
            size = 53, capacity = 73
            size = 54, capacity = 73
            size = 55, capacity = 73
            size = 56, capacity = 73
            size = 57, capacity = 73
            size = 58, capacity = 73
            size = 59, capacity = 73
            size = 60, capacity = 73
            size = 61, capacity = 73
            size = 62, capacity = 73
            size = 63, capacity = 73
            size = 64, capacity = 73
            size = 65, capacity = 73
            size = 66, capacity = 73
            size = 67, capacity = 73
            size = 68, capacity = 73
            size = 69, capacity = 73
            size = 70, capacity = 73
            size = 71, capacity = 73
            size = 72, capacity = 73
            size = 73, capacity = 73
            size = 74, capacity = 109	*****
            size = 75, capacity = 109
            size = 76, capacity = 109
            size = 77, capacity = 109
            size = 78, capacity = 109
            size = 79, capacity = 109
            size = 80, capacity = 109
            size = 81, capacity = 109
            size = 82, capacity = 109
            size = 83, capacity = 109
            size = 84, capacity = 109
            size = 85, capacity = 109
            size = 86, capacity = 109
            size = 87, capacity = 109
            size = 88, capacity = 109
            size = 89, capacity = 109
            size = 90, capacity = 109
            size = 91, capacity = 109
            size = 92, capacity = 109
            size = 93, capacity = 109
            size = 94, capacity = 109
            size = 95, capacity = 109
            size = 96, capacity = 109
            size = 97, capacity = 109
            size = 98, capacity = 109
            size = 99, capacity = 109
            size = 100, capacity = 109
        */
    }

}
